package com.youlu.campus.service.item.Impl;

import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.CaInfo;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.service.ca.CaMaterialConfigService;
import com.youlu.campus.service.cache.CacheCaInfoService;
import com.youlu.campus.service.item.ItemStockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ItemStockServiceImpl implements ItemStockService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CacheCaInfoService cacheCaInfoService;

    @Autowired
    private CaMaterialConfigService caMaterialConfigService;

    private String ITEM_STOCK_KEY = "com.luyou.item.stock.activityId:%s:itemId:%s";

    @Override
    public boolean addStock(String activityId, String itemId, Integer num) {
        log.info(":>>> 开始加库存:{},{},-->:{}", activityId, itemId, num);
        if (StringUtils.isBlank(activityId) || StringUtils.isBlank(itemId) || Objects.isNull(num)) {
            log.error(":>>> 开始加库存参数错误:");
            throw new BusinessException("加库存参数错误");
        }
        String key = this.getItemStockKey(activityId, itemId);
        redisTemplate.opsForValue().increment(key, Long.valueOf(num + ""));
        return true;
    }

    @Override
    public boolean reduceStock(String activityId, String itemId, Integer num) {
        if (StringUtils.isBlank(activityId) || StringUtils.isBlank(itemId) || Objects.isNull(num)) {
            log.error(":>>> 开始减库存参数错误:");
            throw new BusinessException("减库存参数错误");
        }
        String key = this.getItemStockKey(activityId, itemId);
        redisTemplate.opsForValue().decrement(key, Long.valueOf(num + ""));
        return true;
    }

    @Override
    public boolean hasStock(String activityId, String itemId) {
        if (StringUtils.isBlank(activityId) || StringUtils.isBlank(itemId)) {
            log.error(":>>> 开始减库存参数错误:");
            throw new BusinessException("减库存参数错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(itemId));
        CaInfo caInfo = mongoTemplate.findOne(query, CaInfo.class);
        if (Objects.isNull(caInfo)) {
            log.error(":>>> 商品信息为空:{}", itemId);
            throw new BusinessException("商品信息为空");
        }
        if (Objects.isNull(caInfo.getNum())) {
            log.info(":>>> 证书没有配置库存,默认有库存:{}", itemId);
            return true;
        }
        Integer sto = this.getStock(activityId, itemId);
        if (sto.compareTo(caInfo.getNum()) == -1) {
            return true;
        }
        return false;


    }

    @Override
    public boolean hasStockV2(String activityId, String itemId) {
        if (StringUtils.isAnyBlank(activityId, itemId)) {
            log.error(":>>> 减库存参数错误活动:{}| 商品信息:{}", activityId, itemId);
            throw new BusinessException("减库存参数错误");
        }
        CaInfo caInfo = mongoTemplate.findById(itemId, CaInfo.class);
        if (Objects.isNull(caInfo)) {
            log.error(":>>> 活动:{}| 商品信息为空:{}", activityId, itemId);
            throw new BusinessException("商品信息为空");
        }
        List<String> itemMaterialList = caInfo.getItemMaterialList();
        if (CollectionUtils.isEmpty(itemMaterialList)) {
            return true;
        }
        Integer sto = this.getStock(activityId, itemId);
        if (sto.compareTo(caInfo.getNum()) == -1) {
            return true;
        }
        return false;


    }

    @Override
    public Integer getStock(String activityId, String itemId) {
        log.info(":>>> 开始获取库存:{},{}", activityId, itemId);
        if (StringUtils.isBlank(activityId) || StringUtils.isBlank(itemId)) {
            log.error(":>>> 获取库存参数错误:");
            throw new BusinessException("获取库存参数错误");
        }
        String key = this.getItemStockKey(activityId, itemId);
        Long v = redisTemplate.opsForValue().increment(key, 0L);
        log.info(":>>> activityId:{},itemId:{},库存:{}", activityId, itemId, v);
        return v.intValue();
    }

    @Async
    @Override
    public void handleItemStock(String orderNo) {
        log.info(":>>> 开始处理订单库存:{}", orderNo);
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        OrderInfo orderInfo = mongoTemplate.findOne(query, OrderInfo.class);
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getActivityId())) {
            log.error(":>>> 订单:{} 不存在或活动ID不存在", orderNo);
            return;
        }
        List<OOrderInfo> subOrders = mongoTemplate.find(query, OOrderInfo.class);
        if (CollectionUtils.isEmpty(subOrders)) {
            log.error(":>>> 订单:{} 子订单不存在", orderNo);
            return;
        }
        for (OOrderInfo oOrderInfo : subOrders) {
            if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
                //统计已售数量
                CaInfo caInfo = cacheCaInfoService.findById(oOrderInfo.getItemInfoId());
                if (Objects.nonNull(caInfo)) {
                    //获取证书材质
                    List<String> itemMaterialList = caInfo.getItemMaterialList();
                    if (!CollectionUtils.isEmpty(itemMaterialList)) {
                        for (String itemMaterialId : itemMaterialList) {
                            caMaterialConfigService.setSoldCount(itemMaterialId, oOrderInfo.getNum());
                        }
                    }
                }
                boolean hasStock = this.hasStock(orderInfo.getActivityId(), oOrderInfo.getItemInfoId());
                log.info(":>>> 活动:{} 商品:{} 是否有库存:{}", orderInfo.getActivityId(), oOrderInfo.getItemInfoId(), hasStock);
                this.addStock(orderInfo.getActivityId(), oOrderInfo.getItemInfoId(), oOrderInfo.getNum());
                Query querySubOrder = new Query().addCriteria(Criteria.where("id").is(oOrderInfo.getId()));
                Update update = new Update();
                update.set("overbought", !hasStock);
                update.set("date", new Date());
                mongoTemplate.updateFirst(querySubOrder, update, OOrderInfo.class);
            }
        }
    }

    @Override
    public void deleteStock(String activityId, String itemId) {
        String key = this.getItemStockKey(activityId, itemId);
        this.redisTemplate.delete(key);
    }

    protected String getItemStockKey(String activityId, String itemId) {
        return String.format(ITEM_STOCK_KEY, activityId, itemId);
    }
}
